﻿namespace OpcDaNetClient
{
    public partial class Form_AddItems : Form
    {
        public Form_AddItems()
        {
            InitializeComponent();
        }
        #region " Declaration "

        private OpcDaNet.Da.Server m_OpcServer;
        private System.String m_SelectedItem;
        private Int32 m_MaxItems = 10;
        private String m_Separator = ";";

        #endregion

        #region " Properties "


        // hand over the server 
        public OpcDaNet.Da.Server OPCServer
        {
            set { this.m_OpcServer = value; }
        }

        // returns the item name
        public String ItemName
        {
            get { return this.m_SelectedItem; }
        }

        // maximum numbers of items
        public Int32 MaxItems
        {
            get { return this.m_MaxItems; }
            set { this.m_MaxItems = value; }
        }

        // separator sign for return string
        public String SeparatorSign
        {
            get { return this.m_Separator; }
            set { this.m_Separator = value; }
        }

        #endregion

        // Step: 20
        //
        // browse for opc items
        #region " Form events "

        //
        // initialize form 
        private void Form_AddItems_Load(object sender, EventArgs e)
        {
            try
            {
                this.TextBox_SelectedItem.Text = String.Empty;
                this.ListBox_Available_Items.SelectedIndex = -1;
            }
            catch (Exception except)
            {
                this.ShowExceptionInfo(except);
            }
        }

        //
        // copy selected item/s from the list to the text box
        private void ListBox_Available_Items_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                this.TextBox_SelectedItem.Text = String.Empty;

                // check max number of elements
                Int32 cntSelItems = this.ListBox_Available_Items.SelectedItems.Count;
                if (!(this.Button_Add_Item.Enabled =
                    !this.ShowMessageToManyItems(cntSelItems > this.m_MaxItems)))
                    return;

                // add items to text box
                String separator;
                separator = this.m_Separator;
                cntSelItems--;
                for (Int32 index = 0; index <= cntSelItems; index++)
                {
                    if (index == cntSelItems)
                        separator = "";
                    this.TextBox_SelectedItem.Text +=
                        this.ListBox_Available_Items.SelectedItems[index].ToString() + separator;
                }
            }
            catch (Exception except)
            {
                this.ShowExceptionInfo(except);
            }
        }

        //
        // accept selected item by douple click
        private void ListBox_Available_Items_DoubleClick(object sender, EventArgs e)
        {
            try
            {
                this.DialogResult = DialogResult.OK;
                Button_Add_Item_Click(sender, e);
            }
            catch (Exception except)
            {
                this.ShowExceptionInfo(except);
            }
        }

        //
        // check for maximum numbers of items
        private void TextBox_SelectedItem_TextChanged(object sender, EventArgs e)
        {
            try
            {
                // check max number of elements
                String[] items = this.TextBox_SelectedItem.Text.Split(this.m_Separator.ToCharArray());
                this.Button_Add_Item.Enabled = !this.ShowMessageToManyItems(items.Length > this.m_MaxItems);
            }
            catch (Exception except)
            {
                this.ShowExceptionInfo(except);
            }
        }

        // Step: 20
        //
        // browse opc server items - add all opc server items to the list
        // > If the item are not known by the server, you have to write the item 
        //   name manually into the text box
        private void Button_BrowseItems_Click(object sender, EventArgs e)
        {
            try
            {
                // show hour glas
                this.Cursor = Cursors.WaitCursor;

                // check precondition
                Debug.Assert(this.m_OpcServer != null);
                if (this.m_OpcServer == null)
                    return;

                // clear list, stop updating
                this.ListBox_Available_Items.BeginUpdate();
                this.ListBox_Available_Items.Items.Clear();

                // Step: 20.1
                //
                // browse items
                OpcDaNet.Da.BrowseFilters filters = new OpcDaNet.Da.BrowseFilters();
                filters.ElementNameFilter = "";
                filters.BrowseFilter = OpcDaNet.Da.browseFilter.all;
                filters.ReturnAllProperties = false;
                filters.ReturnPropertyValues = false;

                OpcDaNet.ItemIdentifier itemID = new OpcDaNet.ItemIdentifier();
                itemID.ItemName = "";

                this.BrowseItems(itemID, filters);
            }
            catch (Exception except)
            {
                this.ShowExceptionInfo(except);
            }
            finally
            {
                //update list box
                this.ListBox_Available_Items.EndUpdate();

                // restore cursor
                this.Cursor = Cursors.Default;
            }
        }

        //
        // provide selected items in form property
        private void Button_Add_Item_Click(object sender, EventArgs e)
        {
            try
            {
                this.m_SelectedItem = this.TextBox_SelectedItem.Text;
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
            catch (Exception except)
            {
                this.ShowExceptionInfo(except);
            }
        }

        //
        // close form
        private void Button_Close_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        #endregion

        // Step: 20
        //
        // browse for opc items
        #region " auxiliary functions "

        // Step: 20.2
        //
        // recursion - browse items
        private void BrowseItems(OpcDaNet.ItemIdentifier itemIdent, OpcDaNet.Da.BrowseFilters filters)
        {
            try
            {
                //variables used for browsing 
                OpcDaNet.Da.BrowsePosition opcBrowsePosition;
                OpcDaNet.Da.BrowseElement[] opcBrowseElements;
                String itemName;

                // check precondition
                Debug.Assert(this.m_OpcServer != null);
                if (this.m_OpcServer == null)
                    return;

                // Step: 20.2
                //
                // browse items
                opcBrowseElements = this.m_OpcServer.Browse(itemIdent, filters, out opcBrowsePosition);

                // adds each element to the list
                foreach (OpcDaNet.Da.BrowseElement opcBrowseElement in opcBrowseElements)
                {
                    //
                    // avoid errors while using .NET API 1.30
                    if (opcBrowseElement.ItemName != null)
                        itemName = opcBrowseElement.ItemName;
                    else
                        itemName = opcBrowseElement.Name;




                    this.ListBox_Available_Items.Items.Add(itemName);
                    if (this.ListBox_Available_Items.Items.Count > 20)
                    {
                    }

                    // check on subordinate items
                    if (opcBrowseElement.HasChildren == true)
                    {
                        // set branch to search
                        OpcDaNet.ItemIdentifier opcItemIdent = new OpcDaNet.ItemIdentifier();
                        opcItemIdent.ItemName = itemName; // opcBrowseElement.ItemName;
                        this.BrowseItems(opcItemIdent, filters);
                    }
                }
            }
            catch
            {
            }
        }

        public void Clear()
        {
            this.ListBox_Available_Items.Items.Clear();
        }

        private void ShowExceptionInfo(Exception except)
        {
            StringBuilder sbText, sbCaption;
            sbText = new StringBuilder(except.Message);
            sbCaption = new StringBuilder("Exception caugth in ");
            sbCaption.Append(this.Text);
            MessageBox.Show(sbText.ToString(), sbCaption.ToString(),
                MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

        private Boolean ShowMessageToManyItems(Boolean show)
        {
            if (show)
                MessageBox.Show("To many Items selected!\r\nMaximum Items = " + this.m_MaxItems.ToString(),
                    this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);

            return show;
        }

        #endregion

    }
}
